/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package emissorudp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;

/**
 *
 * @author Diego
 */
public class Emissor
{

    InetAddress groupAddress;
    int serverPort = 7000;
    DatagramSocket socket;
    DatagramPacket dg;
    int tamanhoMaximo = 5;
    int tentativas = 5;

    public Emissor() throws SocketException
    {
        socket = new DatagramSocket();
    }

    public void config(String destino, int porta) throws UnknownHostException
    {
        serverPort = porta;
        groupAddress = InetAddress.getByName(destino);
    }

    public void criaPctEManda(byte[] vetorzao) throws IOException
    {
        System.out.println("Criando pacote...");
        dg = new DatagramPacket(vetorzao, 0, vetorzao.length, groupAddress, serverPort);
        this.mandar();
    }

    public void mandar() throws IOException
    {
        System.out.println("Mandando pacote");
        socket.send(dg);
    }

    public DatagramPacket getACK() throws IOException
    {
        byte[] buffer = new byte[tamanhoMaximo];
        DatagramPacket request = new DatagramPacket(buffer, buffer.length);
        socket.receive(request);
        return request;
    }

    public void emitirPDestino(byte[] informacao, int tipo) throws IOException
    {

        if (informacao.length > tamanhoMaximo)
        {
            int aux = (informacao.length / tamanhoMaximo);

            if (informacao.length % tamanhoMaximo != 0)
            {
                aux++;
            }
            System.out.println("Total de pacotes: " + aux);


            socket.setSoTimeout(10000);
            DatagramPacket receive = null;

            byte alternando = 0;
            boolean sair = false;
            for (int i = 0; i < aux; i++)
            {
                tentativas = 5;
                do
                {
                    byte[] temp = Arrays.copyOfRange(informacao, i * tamanhoMaximo, tamanhoMaximo + i * tamanhoMaximo);

                    byte[] temp2 = new byte[temp.length + 2];

                    temp2[0] = alternando;
                    temp2[1] = (byte) tipo;
                    
                    for (int j = 0; j < temp.length; j++)
                    {
                        temp2[j + 2] = temp[j];
                    }

                    this.criaPctEManda(temp2);

                    receive = this.getACK();

                    if (receive == null)
                    {
                        System.out.println("[" + i + "]\t-- Estourou o tempo, não recebi ACK. Reenviando...\n\tTentativas restantes: " + tentativas);
                    } else
                    {
                        byte[] valor = receive.getData();
                        System.out.println("[" + i + "]RECEBIMENTO ACK: valor 0: <" + valor[0] + ">");

                        if (valor[0] != alternando || valor[1] != 'A')
                        {
                            System.out.println("ACK inválido!");
                            receive = null;
                        } else
                        {
                            System.out.println("[" + receive.getAddress().getHostAddress() + "] - ACK");
                        }
                    }

                    tentativas--;

                    if (tentativas == 0)
                    {
                        socket.close();
                        System.out.println("Tentativas esgotadas, fechando conexão...");
                        sair = true;
                        break;
                    }
                    alternando = (byte) ((alternando == 0) ? 1 : 0);

                } while (receive == null);
                if (sair)
                {
                    break;
                }
            }
            System.out.println("Enviando todos os pacotes.");

        }


    }
}
